from nicegui import ui
import pandas as pd
import plotly.express as px
import os
import logging

# 日志配置
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

def load_data():
    if os.path.exists('data/prices.csv'):
        df = pd.read_csv('data/prices.csv')
        df['date'] = pd.to_datetime(df['date'], errors='coerce')
        df.dropna(subset=['date', 'symbol', 'close'], inplace=True)
        logger.info(f"本地数据加载成功，形状: {df.shape}")
        return df[['symbol', 'date', 'open', 'high', 'low', 'close', 'volume']]
    else:
        logger.warning("无本地数据，生成模拟数据")
        return generate_sample_data()

def generate_sample_data():
    import numpy as np
    dates = pd.date_range(end=pd.Timestamp.now(), periods=252, freq='B')
    symbols = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA', 'AIV', 'FTV']
    data = []
    for symbol in symbols:
        prices = np.random.rand(len(dates)) * 100 + 50
        for date in dates:
            open_p = prices[0]
            close_p = open_p * (1 + np.random.normal(0, 0.02))
            data.append({
                'symbol': symbol,
                'date': date,
                'open': round(open_p, 2),
                'close': round(close_p, 2),
            })
        prices = np.roll(prices, -1)
    return pd.DataFrame(data)

def get_chart(df, symbol, chart_type):
    df_sym = df[df['symbol'] == symbol]
    if chart_type == '收盘价走势':
        return px.line(df_sym, x='date', y='close', title=f'{symbol} 收盘价走势')
    elif chart_type == '收益率分布':
        df_sym['return'] = (df_sym['close'] - df_sym['open']) / df_sym['open']
        return px.histogram(df_sym, x='return', nbins=50, title=f'{symbol} 收益率分布')
    elif chart_type == '年交易量统计':
        df_sym['year'] = df_sym['date'].dt.year
        return px.bar(df_sym.groupby('year').size().reset_index(),
                      x='year', y=0, title=f'{symbol} 年交易天数统计')
    return None

def create_dashboard():
    df = load_data()
    symbols = sorted(df['symbol'].unique())

    ui.label('纽约证券交易所数据分析系统').classes('text-3xl font-bold text-center my-4')

    # 👉 强制外部容器 flex 横向排布，撑满视口高度
    with ui.element('div').classes('flex w-full h-[80vh]'):
        # 左侧筛选区
        with ui.column().classes('w-1/5 bg-gray-100 p-4 h-full'):
            ui.label('数据筛选').classes('text-xl font-bold mb-4')
            ui.label('股票:').classes('mt-2')
            symbol_select = ui.select(symbols, value=symbols[0])
            ui.label('图表类型:').classes('mt-4')
            chart_type = ui.radio(
                ['收盘价走势', '收益率分布', '年交易量统计'],
                value='收盘价走势',
            ).classes('flex flex-col gap-2')

            def refresh_chart():
                symbol = symbol_select.value
                ct = chart_type.value
                logger.info(f'更新图表：{ct} | 股票：{symbol}')
                chart_container.clear()
                with chart_container:
                    fig = get_chart(df, symbol, ct)
                    if fig:
                        ui.plotly(fig).classes('w-full h-full')

            symbol_select.on('update:model-value', refresh_chart)
            chart_type.on('update:model-value', refresh_chart)

        # 右侧图表区
        with ui.column().classes('w-4/5 p-4 h-full'):
            chart_container = ui.element('div').classes('w-full h-full')
            refresh_chart()

    ui.label('© 2025 大数据编程平台课程项目').classes('text-center mt-4 text-gray-500')


if __name__ in {"__main__", "__mp_main__"}:
    create_dashboard()
    ui.run(
        title='证券分析系统',
        dark=False,
        port=8080,
        reload=False
    )
